package vip.zhenzicheng.jvm;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;

/**
 * 自定义类加载器
 *
 * @author zhenzicheng
 * @date 2022-05-14 22:57
 */
public class MyClassLoaderTest {

  public static void main(String[] args) throws ReflectiveOperationException {
    // 初始化自定义类加载器，会先初始化父类ClassLoader，然后会将自定义类加载器的父加载器设置为应用程序加载器AppClassLoader
    MyClassLoader classLoader = new MyClassLoader("E:/test");
    Class<?> clazz = classLoader.loadClass("vip.zhenzicheng.demo.HelloWorld");

    // 同级目录下创建HelloWorld类
    Object obj = clazz.newInstance();
    Method method = clazz.getMethod("toString");
    Object result = method.invoke(obj);
    System.out.println(result);
    System.out.println(clazz.getClassLoader().getClass().getName());
  }


  static class MyClassLoader extends ClassLoader {
    private String classPath;

    public MyClassLoader(String classPath) {
      this.classPath = classPath;
    }

    @Override
    protected Class<?> findClass(String name) {
      try {
        byte[] data = loadByte(name);
        // defineClass将一个字节数组转为Class对象，这个字节数组是class文件读取后最终的字节数组
        return super.defineClass(name, data, 0, data.length);
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }

    private byte[] loadByte(String name) throws IOException {
      String fileName = name.replaceAll("\\.", "/");
      FileInputStream fis = new FileInputStream(classPath + "/" + fileName + ".class");
      int len = fis.available();
      byte[] data = new byte[len];
      fis.read(data);
      fis.close();

      return data;
    }
  }
}
